import { delay as delayFun } from './tools';
import { isObject, isNumber } from './type';
import store from '@/store/index.js';
import { loginPage, loginSuccessPage, webViewPage } from '@/config';
import { isHttp } from './regexp';
/**
 * 进入动画
 */
export const goAnims = {
  left: 'slide-in-left',  // 新窗体从左侧进入
  right: 'slide-in-right', // 新窗体从右侧进入
  top: 'slide-in-top',  // 新窗体从顶部进入
  bottom: 'slide-in-bottom',  // 新窗体从底部进入
  pop: 'pop-in',  // 新窗体从左侧进入，且老窗体被挤压而出
  fade: 'fade-in',  // 新窗体从透明到不透明逐渐显示
  zoom: 'zoom-out',  // 新窗体从小到大缩放显示
  zoomFade: 'zoom-fade-out',  // 新窗体从小到大逐渐放大并且从透明到不透明逐渐显示
  none: 'none'  // 无动画
}

/**
 * 离开动画
 */
export const backAnims = {
  left: 'slide-out-left',  // 当前窗体从左侧离开
  right: 'slide-out-right', // 当前窗体从右侧离开
  top: 'slide-out-top',  // 当前窗体从顶部离开
  bottom: 'slide-out-bottom',  // 当前窗体从底部离开
  pop: 'pop-out',  // 当前窗体从左侧离开，且老窗体被挤压而出
  fade: 'fade-out',  // 当前窗体从透明到不透明逐渐显示
  zoom: 'zoom-in',  // 当前窗体从小到大缩放显示
  zoomFade: 'zoom-fade-in',  // 当前窗体从小到大逐渐放大并且从透明到不透明逐渐显示
  none: 'none'  // 无动画
}

const types = {
  go: 'navigateTo',
  replace: 'redirectTo',
  reset: 'reLaunch',
  tab: 'switchTab',
  back: 'navigateBack',
}

// 页面数据储存对象
const _pageParams = {}

let _redirectPage = '';

/**
 * 获取页面参数
 * @param {String} key 要取出的键名，不传使用默认
 */
export function getParams(key = 'default') {
  return _pageParams[key];
}

/**
 * 设置页面参数
 * @param {any} arg1 只有一个参数时，为储存值，键名使用默认。当两个参数时，为储存的键名
 * @param {any} arg2 储存的数据
 */
export function setParams(arg1, arg2 = undefined) {
  if(arg2 === undefined) {
    _pageParams.default = arg1;
  } else {
    _pageParams[arg1] = arg2;
  }
}

/**
 * 处理页面路径
 * @param {String} url 页面路径
 */
export function handlePageUrl(url) {
  if(url.indexOf('/') === 0 || url.indexOf('.') === 0) {
    return url;
  } else {
    return '/pages/' + url;
  }
}

/**
 * 页面跳转 基础函数
 * @param {Object|String|Number} args 配置对象或字符串、数字
 * @param {String} type 类型
 * @param {Boolean} isWeb 是否为打开网址
 */
function pageBase(args, type, isWeb) {
  if(isWeb) setParams('webview', args);  // 打开网址前，将传递的参数存储
  type = types[type] || types.go;

  // 传递非对象参数
  if(!isObject(args)) {

    // 回退， 参数类型为NUmber
    if(type === 'navigateBack') { 
      args = { delta: Number(args) || 1 };

    // 其他非webview页面（字符串验证）
    } else if (!isWeb) {
      if(typeof args == 'string') args = { url: handlePageUrl(args) };
      else throw '请传入页面地址！';
      
    // webview页面（网址验证）
    } else {
      if(isHttp(args)) args = { url: handlePageUrl(webViewPage) };
      else throw '请传入要打开的网址！';
    }

  // 传递对象参数
  } else {
    
    // 打开网址时，覆盖url为webview页面
    if(isWeb) args.url = webViewPage;
    
    // 配置跳转页面为tabbar页面
    if(args.type === 'tab') type = types['tab'];

    // 配置登录，但没有登录，跳转到登录页面
    if(args.login && type !== 'navigateBack' && !store.getters.token) {
      type = types['go'];
      _redirectPage = args.url;
      args.url = loginPage;
    } else {
      _redirectPage = '';
    }
    
    // 支持配置动画的类型，做下别名处理
    if(type.indexOf('navigate') === 0) {
      // 扩展两个别名，写着比较短。
      if(args.animTime) args.animationDuration = args.animTime; // 动画时间
      if(args.animType && goAnims[args.animType]) {   // 动画类型
        if(type === 'navigateBack') args.animationType = backAnims[args.animType];
        else args.animationType = goAnims[args.animType];
      }
    }
    
    // 对url进行处理
    if(args.url) args.url = handlePageUrl(args.url);
  }
  
  let isCancel = false;
  const promise = new Promise(async (resolve, reject) => {
    
    // 延时执行
    if(isNumber(args.delay)) await delayFun(args.delay);
    
    // 默认配置
    const defConf = {
      success: (res) => {
        resolve(res);
      },
      fail: (err) => {
        reject(err);
      }
    }

    if(!isCancel) {
      // 如果当前是外部打开网址
      if(isWeb && args.out && args.url !== handlePageUrl(loginPage)) {
        // #ifdef H5
				window.open(args.web);
				// #endif
				// #ifdef APP-PLUS
				plus.runtime.openURL(args.web);
				// #endif
        resolve(args);
      } else {
        uni[type]({ ...defConf, ...args });
      }
    }
  });
  
  // 添加取消方法
  promise.abort = (...args) => {
    isCancel = true;
    return Promise.resolve(...args);
  };
  
  return promise;
}

/**
 * 普通跳转
 * @param {String|Object} args 跳转地址或配置对象
 */
export function go(args) {
  return pageBase(args, 'go');
}

/**
 * 替换跳转
 * @param {String|Object} args 跳转地址或配置对象
 */
export function replace(args) {
  return pageBase(args, 'replace')
}

/**
 * 清除历史跳转
 * @param {String|Object} args 跳转地址或配置对象
 */
export function reset(args) {
  return pageBase(args, 'reset')
}

/**
 * 跳转tabbar页面
 * @param {String|Object} args 跳转地址或配置对象
 */
export function tab(args) {
  return pageBase(args, 'tab')
}

/**
 * 返回
 * @param {String|Object} args 跳转地址或配置对象
 */
export function back(args) {
  return pageBase(args, 'back')
}

/**
 * 打开网址
 * @param {String|Object} args 网址或配置对象
 */
export function goWeb(args) {
  return pageBase(args, 'go', true);
}

/**
 * 登录成功执行重定向
 * @param {String|Object} args 跳转地址或配置对象
 */
export function loginSuccess() {
  const webParams = getParams('webview') || {};
  const webPage = handlePageUrl(webViewPage);

  // 重定向到内部页面
  if(_redirectPage !== webPage || (_redirectPage === webPage && !webParams.out)) {
    return pageBase(_redirectPage || handlePageUrl(loginSuccessPage), 'replace');
    
  // 重定向到外部网址
  } else {
    goWeb({ ...webParams, delay: undefined}).then(res => {
      back({delay: 300}); 
    }).catch(err => {});
  }
}

